﻿using NUnit.Framework;
using Payroll.Biz.Legacy.Models;
using System;

namespace Payroll.Biz.Legacy.Test.GPT
{
    /// <summary>
    /// Prompt:
    /// Here is a C# class, I want you to help me write equals assertion method by using NUnit.
    /// [Employee.cs] without Equals and GetHashCode methods.
    /// 
    /// Response:
    /// First, let's implement the Equals method in the Employee class:
    /// <code>
    /// public override bool Equals(object obj)  
    /// {  
    ///     if (obj is Employee employee)  
    ///     {  
    ///         return Id == employee.Id &&  
    ///                Name == employee.Name &&  
    ///                Address == employee.Address &&  
    ///                EqualityComparer<IPaymentSchedule>.Default.Equals(Schedule, employee.Schedule) &&  
    ///                EqualityComparer<IPaymentMethod>.Default.Equals(Method, employee.Method) &&  
    ///                EqualityComparer<IAffiliation>.Default.Equals(Affiliation, employee.Affiliation) &&  
    ///                EqualityComparer<IPaymentClassification>.Default.Equals(Classification, employee.Classification);  
    ///     }  
    ///     return false;  
    /// }  

    /// public override int GetHashCode()  
    /// {  
    ///     return HashCode.Combine(Id, Name, Address, Schedule, Method, Affiliation, Classification);  
    /// }  
    /// </code>
    /// </summary>
    [TestFixture]
    public class GenerateEquals2
    {
        [Test]
        public void Equals_ShouldReturnTrueForSameObject()
        {
            Guid id = Guid.NewGuid();
            MockClassification classification = new MockClassification();
            Employee employee = new Employee(id, "123 Main St", classification)
            {
                Name = "John Doe",
                Schedule = new MockSchedule(),
                Method = new MockMethod(),
                Affiliation = new MockAffiliation()
            };

            Assert.IsTrue(employee.Equals(employee));
        }

        [Test]
        public void Equals_ShouldReturnTrueForEqualObjects()
        {
            Guid id = Guid.NewGuid();
            MockClassification classification = new MockClassification();
            Employee employee1 = new Employee(id, "123 Main St", classification)
            {
                Name = "John Doe",
                Schedule = new MockSchedule(),
                Method = new MockMethod(),
                Affiliation = new MockAffiliation()
            };

            Employee employee2 = new Employee(id, "123 Main St", classification)
            {
                Name = "John Doe",
                Schedule = new MockSchedule(),
                Method = new MockMethod(),
                Affiliation = new MockAffiliation()
            };

            Assert.IsTrue(employee1.Equals(employee2));
        }

        [Test]
        public void Equals_ShouldReturnFalseForDifferentObjects()
        {
            MockClassification classification1 = new MockClassification();
            MockClassification classification2 = new MockClassification();
            Employee employee1 = new Employee(Guid.NewGuid(), "123 Main St", classification1)
            {
                Name = "John Doe",
                Schedule = new MockSchedule(),
                Method = new MockMethod(),
                Affiliation = new MockAffiliation()
            };

            Employee employee2 = new Employee(Guid.NewGuid(), "456 Elm St", classification2)
            {
                Name = "Jane Doe",
                Schedule = new MockSchedule(),
                Method = new MockMethod(),
                Affiliation = new MockAffiliation()
            };

            Assert.IsFalse(employee1.Equals(employee2));
        }
    }

    // Mock classes for testing purposes, ignored...

    #region Prompt:Please do not leverage Equals and GetHashCode methods from that class. --- not good

    [TestFixture]
    public class GenerateEquals3
    {
        [Test]
        public void Employees_ShouldHaveSameProperties()
        {
            Guid id = Guid.NewGuid();
            MockClassification classification = new MockClassification();
            Employee employee1 = new Employee(id, "123 Main St", classification)
            {
                Name = "John Doe",
                Schedule = new MockSchedule(),
                Method = new MockMethod(),
                Affiliation = new MockAffiliation()
            };

            Employee employee2 = new Employee(id, "123 Main St", classification)
            {
                Name = "John Doe",
                Schedule = new MockSchedule(),
                Method = new MockMethod(),
                Affiliation = new MockAffiliation()
            };

            Assert.AreEqual(employee1.Id, employee2.Id);
            Assert.AreEqual(employee1.Name, employee2.Name);
            Assert.AreEqual(employee1.Address, employee2.Address);
            Assert.AreEqual(employee1.Schedule.GetType(), employee2.Schedule.GetType());
            Assert.AreEqual(employee1.Method.GetType(), employee2.Method.GetType());
            Assert.AreEqual(employee1.Affiliation.GetType(), employee2.Affiliation.GetType());
            Assert.AreEqual(employee1.Classification.GetType(), employee2.Classification.GetType());
        }

        [Test]
        public void Employees_ShouldHaveDifferentProperties()
        {
            MockClassification classification1 = new MockClassification();
            MockClassification classification2 = new MockClassification();
            Employee employee1 = new Employee(Guid.NewGuid(), "123 Main St", classification1)
            {
                Name = "John Doe",
                Schedule = new MockSchedule(),
                Method = new MockMethod(),
                Affiliation = new MockAffiliation()
            };

            Employee employee2 = new Employee(Guid.NewGuid(), "456 Elm St", classification2)
            {
                Name = "Jane Doe",
                Schedule = new MockSchedule(),
                Method = new MockMethod(),
                Affiliation = new MockAffiliation()
            };

            Assert.AreNotEqual(employee1.Id, employee2.Id);
            Assert.AreNotEqual(employee1.Name, employee2.Name);
            Assert.AreNotEqual(employee1.Address, employee2.Address);
            Assert.AreNotEqual(employee1.Classification, employee2.Classification);
        }
    }

    #endregion
}
